﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Text;
using log4net;
using PYun.API;
using PYun.API.Reply;
using PYun.API.Request;
using PYun.Utils;


namespace VirtualWall.CloudLogic
{
    public class PYunService : AbstractServiceAPI
    {
        Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
        Configuration mainConfig = ConfigurationManager.OpenExeConfiguration("双髻鲨汽车衡称重软件.exe");

        private static readonly ILog log = LogManager.GetLogger("PYunService");
        /// <summary>
        /// 提前拦截请求, 若请求被处理则不会触发其他方法回调
        /// </summary>
        /// <param name="serviceName"></param>
        /// <param name="args"></param>
        /// <param name="reply"></param>
        /// <returns>true - 请求已拦截处理完成; false - 请求未处理</returns>
        public override bool HookRequest(string serviceName, IDictionary<string, string> args,
            PYun.Protocol.Payload.ExecutePayload reply)
        {
            //// 对于SDK尚未封装的接口可在这手动拦截实现
            //if ("service.parking.realtime".Equals(serviceName))
            //{
            //    // 模拟拦截实时车位
            //    // TODO 处理业务逻辑
            //    IDictionary<string, string> parameters = new Dictionary<string, string>();
            //    parameters["total"] = "1000";
            //    parameters["parking"] = "10";
            //    parameters["available"] = "900";


            //    // 设置返回结果
            //    reply.ResultCode = "1001";
            //    reply.Message = "处理成功";
            //    reply.Parameters = parameters;
            //    // 注意: 拦截处理后返回true表示已经处理过了
            //    return true;

            //}

            //// 订单支付结果通知
            //if ("service.parking.payment.result".Equals(serviceName))
            //{
            //    // 模拟拦截实时车位
            //    // TODO 处理业务逻辑
            //    IDictionary<string, string> parameters = new Dictionary<string, string>();
            //    parameters["total"] = "1000";
            //    parameters["parking"] = "10";
            //    parameters["available"] = "900";

            //    //获取当前这次停车记录，并修改停车支付状态为 1，电子支付
            //    SQLDataAccess.GetWeighingRecord(reply);

            //    // 设置返回结果
            //    reply.ResultCode = "1001";
            //    reply.Message = "处理成功";
            //    reply.Parameters = parameters;
            //    // 注意: 拦截处理后返回true表示已经处理过了
            //    return true;

            //}


            // 其他未处理返回false则SDK会自动处理
            return false;
        }

        /// <summary>
        /// 查询停车费用
        /// 1001 订单获取成功，业务参数将返回。
        /// 1002 未查询到停车信息。
        /// 1003 月卡车辆，不允许缴费。
        /// 1500 接口处理异常。
        /// 
        /// // 获取订单代码
        /// if (card 不合法 && !plate 合法) {
        ///     return 1400; // 返回参数错误
        /// }
        /// // 1. 检查订单
        /// ParkingOrder parking = 获取停车记录(card, plate) // 根据车牌或停车卡获取停车记录
        /// if (parking 已出场) {
        ///     return 1002; // 无停车记录
        /// }
        /// // 2. 检查是否月卡、次卡等非临停用户
        /// if (parking 非临停) {
        ///     return 1003; // 非临停，返回无需支付停车费
        /// }
        /// // 3. 检查收费情况
        /// if (parking 无需交费) {
        ///     return parking; // 返回停车订单，不含支付单号，包含停车流水
        /// }
        /// // 4. 填充订单数据, 若有优惠，则填充优惠信息；
        /// ParkingBilling billing = 生成停车订单;
        /// parking.parking_order = billing.serial;    // 支付流水...
        /// parking.pay_value = billing.value;  // 实际支付金额
        /// 
        /// return parking; // 返回支付订单。
        /// 
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public override APIReply<ParkingBilling> ParkingBilling(ParkingBillingRequest request)
        {
            try
            {
                //如果不是电子围栏的出场通道的回调，就停止下面的逻辑
                if (request.GateId != "003")
                {
                    return APIReply<ParkingBilling>.newBuilder()
                        .setResultCode(ResultCode.BadRequest)
                        .setMessage("通道无效")
                        .Build();
                }

                //如果是空的车牌号码，就停止下面的逻辑
                if (string.IsNullOrEmpty(AppContext.CurrentOutPlate))
                {
                    return APIReply<ParkingBilling>.newBuilder()
                        .setResultCode(ResultCode.BadRequest)
                        .setMessage("车牌号码无效")
                        .Build();
                }
                request.Plate = AppContext.CurrentOutPlate;
                //检查沉重记录完整性
                var weighingRecord = SQLDataAccess.GetWeighingRecord(request.Plate);
                if (!weighingRecord.IsFinish)
                {
                    return APIReply<ParkingBilling>.newBuilder()
                       .setResultCode(ResultCode.BadRequest)
                       .setMessage("称重记录不完整，禁止通行")
                       .Build();

                }
                //查询本次场内消费的费用
                int feiyong = 0;
                int.TryParse(weighingRecord.Je, out feiyong);
                feiyong = feiyong * 100;//人民币元转换成分
                feiyong = 1;
                //计算本次称重需要的费用，并返回给P云 
                ParkingBilling payload = new ParkingBilling();
                payload.EnterTime = weighingRecord.EntryTime.Value;
                payload.Plate = weighingRecord.Ch;
                payload.ParkingSerial = weighingRecord.Bh;
                payload.ParkingOrder = weighingRecord.Bh;// DateTime.Now.ToString("yyyyMMddHHmmss") + RandomUtil.RandomNumeric(6);
                payload.ParkingTime = Utility.TimeSPanBySeconds(weighingRecord.EntryTime.Value);// 90 * 60;  // 单位秒
                payload.TotalValue = uint.Parse(feiyong.ToString());
                payload.FreeValue = 0;
                payload.PaidValue = 0;
                payload.PayValue = uint.Parse(feiyong.ToString());

                //计算本次停车需要的费用，结合上面的称重费用合计返回给p云
                //因为这里还没有实行停车费用的逻辑，所以这里目前只计算称重
                //的费用，等停车收费逻辑弄好，再加上，目前先更改CarFee表的
                //相关状态和数据
                var noFinish = SQLDataAccess.CarFeeNoFinish(request.Plate);
                noFinish.Tclsh = weighingRecord.Bh;//设定停车表的订单编号，此处跟称重合并收费，所以直接用称重的BH字段，因为此字段唯一。
                                                   //int feiyong = 0;
                                                   //int.TryParse(weighingRecord.Je, out feiyong);
                                                   //feiyong = (feiyong+ noFinish.Fee) * 100;//人民币元转换成分
                                                   //payload.ParkingTime = noFinish.OutDate- noFinish.InDate;
                                                   //payload.TotalValue = uint.Parse(feiyong.ToString());
                                                   //payload.FreeValue = 0;
                                                   //payload.PaidValue = 0;
                                                   //payload.PayValue = uint.Parse(feiyong.ToString());
                SQLDataAccess.UpdateCarFee(noFinish);

                //如果是0元，则无需缴费，平台也不会再调用同步函数，所以这里直接修改数据并开闸
                if (feiyong <= 0)
                {
                    //修改称重的支付状态为电子支付
                    weighingRecord.IsPay = 1;
                    weighingRecord.Zfdw = "0元无需缴费";
                    weighingRecord.Zfje = 0;
                    weighingRecord.Zfsj = DateTime.Now;
                    SQLDataAccess.UpdateWeighingRecord(weighingRecord);

                    //修改停车的支付状态为电子支付
                    noFinish.IsPay = 1;
                    noFinish.Zfdw = "0元无需缴费";
                    noFinish.Zfje = 0;
                    noFinish.Zfsj = DateTime.Now;
                    SQLDataAccess.UpdateCarFee(noFinish);

                    //调用闸机放行车辆
                    AppContext.FlowControl.GoOut(weighingRecord.Ch);
                }

                //返回订单数据给P云
                return APIReply<ParkingBilling>.newBuilder()
                    .setResultCode(ResultCode.Success)
                    .setPayload(payload)
                    .setMessage("成功")
                    .Build();

            }
            catch (Exception e)
            {
                log.Info($"订单获取接口：错误：{e.Message}");
                return APIReply<ParkingBilling>.newBuilder()
                       .setResultCode(ResultCode.InternalServerError)
                        .setMessage(e.Message)
                       .Build();
            }

        }


        /// <summary>
        /// 同步场中支付结果
        /// 1001 接口处理成功，业务参数将返回。
        /// 1403 订单已撤销。
        /// 1500 接口内部处理失败。
        /// 
        /// // 1. 根据parking_order查询订单。
        /// ParkingPayment payment = 根据parking_order查询订单
        /// if (payment == null) {
        ///     return 1002;    // 未找到订单信息
        /// } elseif (payment 已成功处理) {
        ///     return 1001; // 返回处理成功
        /// }
        /// // 2. 根据parking_serial查询停车信息。
        /// ParkingOrder parking = 获取停车记录(parking_serial)；
        /// if (parking 已离场) {
        ///     retuen 1403; // 返回订单撤销，我们会根据这个状态核对订单，如果需要办理退款，我们会办理。
        /// }
        /// // 3. 检查订单是否为最新订单，我们需要保证用户支付的最新订单，才能保证支付金额足够
        /// if (payment 非本次停车最新订单) {
        ///     return 1403; // 返回订单撤销，我们会根据这个状态核对订单，如果需要办理退款，我们会办理。
        /// }
        /// // 4. 更新订单状态并更新总支付金额。
        /// update(parking);
        /// 
        /// return 1001; // 返回处理成功
        /// </summary>
        public override APIReply<object> ParkingPayment(ParkingPaymentRequest request)
        {
            try
            {
                if (request.ParkingSerial == null)
                {
                    return APIReply<object>.newBuilder()
                        .setResultCode(ResultCode.BadRequest)
                        .setMessage("参数无效")
                        .Build();
                }
                //根据订单号获取本次收费车辆的信息，并且修改收费状态 ispay=1 电子支付
                var record = SQLDataAccess.GetWeighingRecordByBh(request.ParkingOrder);

                //查找本车未完成的停车记录，并且修改收费状态 ispay=1 电子支付
                //var noFinish = SQLDataAccess.CarFeeNoFinish(record.Ch);
                var noFinish = SQLDataAccess.GetCarFeeByTclsh(request.ParkingOrder);

                //如果没有找到订单，说明平台传递数据有问题
                if (record == null)
                {
                    return APIReply<object>.newBuilder()
                       .setResultCode(ResultCode.Empty)
                       .setMessage("未找到称重订单信息")
                       .Build();
                }
                //如果没有找到订单，说明平台传递数据有问题
                if (noFinish == null)
                {
                    return APIReply<object>.newBuilder()
                       .setResultCode(ResultCode.Empty)
                       .setMessage("未找到停车订单信息")
                       .Build();
                }

                //修改称重的支付状态为电子支付
                record.IsPay = 1;
                record.Zfdw = request.PayOrigin.ToString();
                record.Zfje = request.Value;
                record.Zfsj = request.PayTime;
                record.Zflsh = request.PaySerial;
                record.Zfdzsm = request.PayOriginDesc;
                SQLDataAccess.UpdateWeighingRecord(record);

                //修改停车的支付状态为电子支付
                noFinish.IsPay = 1;
                noFinish.Zfdw = request.PayOrigin.ToString();
                noFinish.Zfje = request.Value;
                noFinish.Zfsj = request.PayTime;
                noFinish.Zflsh = request.PaySerial;
                noFinish.Zfdzsm = request.PayOriginDesc;
                SQLDataAccess.UpdateCarFee(noFinish);

                //调用闸机放行车辆
                AppContext.FlowControl.GoOut(record.Ch);

                return APIReply<object>.newBuilder()
                    .setResultCode(ResultCode.Success)
                    .Build();
            }
            catch (Exception e)
            {
                log.Info($"支付同步接口：错误：{e.Message}");
                return APIReply<object>.newBuilder()
                    .setResultCode(ResultCode.InternalServerError)
                    .setMessage(e.Message)
                    .Build();
            }
        }

        /// <summary>
        /// 无牌车直接入场请求
        /// 1001 接口处理成功，业务参数将返回。
        /// 1002 未检测到车辆
        /// 1403 短时间重复入场。
        /// 1500 接口处理异常。
        /// </summary>
        public override APIReply<ParkingDetail> ParkingDirectEnter(ParkingDirectEnterRequest request)
        {

            if (string.IsNullOrWhiteSpace(request.Passport))
            {
                return APIReply<ParkingDetail>.newBuilder()
                    .setResultCode(ResultCode.BadRequest)
                    .setMessage("车牌无效")
                    .Build();
            }
            if (string.IsNullOrWhiteSpace(request.GateId))
            {
                return APIReply<ParkingDetail>.newBuilder()
                    .setResultCode(ResultCode.BadRequest)
                    .setMessage("通道无效")
                    .Build();
            }

            if (request.GateId.Trim() == "001")
            { //1次称重入口闸道
                return APIReply<ParkingDetail>.newBuilder()
                      .setResultCode(ResultCode.Success)
                      .Build();
            }
            else if (request.GateId.Trim() == "003")
            { //2次称重入口闸道
                return APIReply<ParkingDetail>.newBuilder()
                  .setResultCode(ResultCode.Success)
                  .Build();
            }
            else
            {
                return APIReply<ParkingDetail>.newBuilder()
                    .setResultCode(ResultCode.BadRequest)
                    .setMessage("通道无效")
                    .Build();
            }

        }

        /// <summary>
        /// 查询停车场实时信息
        /// 1001 获取成功，业务参数将返回。
        /// 1500 接口处理异常。
        /// </summary>
        public override APIReply<ParkingRealtime> ParkingRealtime(ParkingRealtimeRequest request)
        {
            return base.ParkingRealtime(request);
        }

        /// <summary>
        /// 同步停车记录
        /// 1001 获取成功，业务参数将返回。
        /// 1500 接口处理异常。
        /// </summary>
        public override APIReply<ParkingSYNCPayload> ParkingSYNC(ParkingSYNCRequest request)
        {
            return base.ParkingSYNC(request);
        }

        /// <summary>
        /// 更新自动支付状态
        /// 1001 接口处理成功，业务参数将返回。
        /// 1002 停车记录不存在
        /// 1403 车辆已出场。
        /// 1500 接口处理异常。
        /// </summary>
        public override APIReply<object> ParkingAutopayUpdate(ParkingAutopayUpdateRequest request)
        {
            return base.ParkingAutopayUpdate(request);
        }

        /// <summary>
        /// 更新锁车状态
        /// 1001 接口处理成功，业务参数将返回。
        /// 1002 停车记录不存在
        /// 1403 车辆已出场。
        /// 1500 接口处理异常。
        /// </summary>
        public virtual APIReply<object> ParkingLockingUpdate(ParkingLockingUpdateRequest request)
        {
            return base.ParkingLockingUpdate(request);
        }

        /// <summary>
        /// 获取停车详情
        /// 1001 订单查询成功，业务参数将返回。
        /// 1002 未查询到停车信息。
        /// 1500 接口处理异常。
        /// </summary>
        public override APIReply<ParkingDetail> ParkingDetail(ParkingDetailRequest request)
        {
            ParkingPayment payment = new ParkingPayment();
            payment.PayType = PYun.API.Reply.ParkingPayment.PAY_TYPE_CASH;

            ParkingDetail detail = new ParkingDetail();
            detail.PlateColor = ColorType.Blue;
            return base.ParkingDetail(request);
        }

        /// <summary>
        /// 下发停车优惠
        /// 1001 接口处理成功，业务参数将返回。
        /// 1002 停车信息未找到。
        /// 1403 当前车辆已享受其他优惠。
        /// 1500 接口处理异常。
        /// </summary>
        public override APIReply<object> ParkingDiscountCreate(ParkingDiscountCreateRequest request)
        {
            return base.ParkingDiscountCreate(request);
        }

        /// <summary>
        /// 撤销停车优惠
        /// 1001 接口处理成功，业务参数将返回。
        /// 1002 派发信息未找到。
        /// 1403 优惠已使用。
        /// 1500 接口处理异常。
        /// </summary>
        public override APIReply<object> ParkingDiscountDestory(ParkingDiscountDestoryRequest request)
        {
            return base.ParkingDiscountDestory(request);
        }

        /// <summary>
        /// 查询月卡信息
        /// 1001 获取成功，业务参数将返回。
        /// 1002 没有查到相关贵宾记录。
        /// 1500 接口处理异常。
        /// </summary>
        public override APIReply<ParkingVIPPayload> ParkingVIPQuery(ParkingVIPQueryRequest request)
        {
            ParkingVIPPayload payload = new ParkingVIPPayload();
            List<ParkingVIP> Vips = new List<ParkingVIP>();
            ParkingVIP item = new ParkingVIP();
            item.Balance = 10;
            Vips.Add(item);

            payload.SetVips(Vips);

            return APIReply<ParkingVIPPayload>.newBuilder()
                .setPayload(payload)
                .setResultCode(ResultCode.Success)
                .setMessage("NOT IMPLEMENT YET")
                .Build();
        }

        /// <summary>
        /// 下发月卡续费信息
        /// 1001 续费成功，业务参数将返回。
        /// 1002 贵宾信息未找到。
        /// 1403 贵宾已被禁用，需退款。
        /// 1500 接口处理异常。
        /// </summary>
        public override APIReply<object> ParkingVIPRenewal(ParkingVIPRenewalRequest request)
        {
            return base.ParkingVIPRenewal(request);
        }

    }
}
